programming4us
           
 
 
Windows Phone

Windows Phone 7 : Using the Touch Screen (part 6) - Initiating Object Motion

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
7/17/2013 3:44:49 AM

4. Initiating Object Motion

You should now feel comfortable with reading user input from the touch screen. Before we finish examining screen input, let's discuss a couple of common movement patterns that you might want to include in your games: dragging and flicking.

4.1. Dragging Objects

The code required to drag objects is very straightforward. If a touch point is held, we simply need to find the movement distance between its current and previous locations and add it to the position of the objects that are being dragged.

The first part of dragging some objects is to allow them to be selected. Sometimes the selection will be a separate input from the drag (where the objects are tapped and then dragged afterward), but in most cases a drag will include object selection when contact with the screen is first established.

This is easy to do when using raw input as we can look for a TouchLocation.State value of Pressed. When it is detected, the object selection can be established ready for the objects to be dragged.

If we are using gestures, though, we have a problem: there is no gesture that is triggered when contact is first established with the screen. The tap gesture fires only when contact is released, and the drag gestures fire only once the touch point has moved far enough to be considered as actually dragging. So how do we perform the object selection?

The answer is to once again use raw input for this. Raw input and gestures can be mixed together so that the initial screen contact for object selection comes from raw input, and the dragging comes from a gesture.

Once the objects are selected, we can update them in response to the touch point moving around the screen. When using gestures, we simply look for one of the drag gestures and read out the Delta property of the GestureSample object. This contains the distance that the touch point has moved on each axis, which is exactly what we need.

Don't forget that the HorizontalDrag and VerticalDrag gestures will provide only delta values for the appropriate axis. There is no need to cancel out or ignore the other movement axis because XNA takes care of this automatically.


To calculate the delta using raw input, we obtain the previous touch position using the TryGetPreviousLocation function and subtract that position from the current position. The result is the movement distance. The code for this is shown in Listing 13.

Example 13. Calculating the drag delta when using raw touch input
if (touches[0].State == TouchLocationState.Moved)
        {
            // Drag the objects. Make sure we have a previous position
            TouchLocation previousPosition;
            if (touches[0].TryGetPreviousLocation(out previousPosition))
            {
                // Calculate the movement delta
                Vector2 delta = touches[0].Position - previousPosition.Position;
                ProcessDrag(delta);
            }
        }

					  

Whichever method we used to calculate the delta, we now simply add the delta value to the position of all the selected sprites. They will then follow the touch location as it is moved around the screen.

Two example projects are provided to demonstrate this: DragAndFlick is a gesture-based implementation, whereas DragAndFlickRaw achieves the same effect using raw touch data. Both projects contain a SelectableSpriteObject class based on the one from the HitTesting project and contain identical functions for selecting the sprites at a point (SelectAllMatches), deselecting the sprites (DeselectAllObjects), and dragging the selected objects (ProcessDrag). There are some additional properties present, but we will look at them in the next section.

Try running both of the examples and see how they work. You'll notice that they don't feel exactly the same, even though they do essentially the same thing. The gesture-based project has a delay between when you move the touch point and when the objects actually respond to the movement. The reason for this is that the gesture system waits for the touch point to move a small distance before it considers a drag gesture to have started. As a result, it feels a little less responsive.

The raw touch input assumes that all movement is part of a drag, so there is no delay at all. As a result, it feels a lot more responsive. Bear this difference in mind when considering the input options that are available when you are coding your games.

4.2. Flicking Objects

With the object movement under our control, it is sometimes useful to allow the user to flick or throw them across the screen. This is often known as kinetic movement, and it consists of retaining the velocity at which the object is moving when the touch point is released and continuing to move the object in the same direction, gradually decreasing the speed to simulate friction.

To control the movement of the object, some new code has been added to the SelectableSpriteObject class. This code consists of a new Vector2 property called KineticVelocity, which tracks the direction and speed of movement; a float property called KineticFriction, which controls how strong the friction effect is (as a value between 0 and 1), and an Update override that applies the movement and the friction.

The Update code simply adds the velocity to the position, and then multiplies the velocity by the friction value. This function is shown in Listing 14. Notice how it uses the MathHelper.Clamp function to ensure that the friction is always kept between 0 and 1 (values outside of this range would cause the object to accelerate, which is probably undesirable, though perhaps it might be useful in one of your games!).

Example 14. Updating the SelectableSpriteObject to allow it to observe kinetic movement
public override void Update(GameTime gameTime)
    {
        base.Update(gameTime);

        // Is the movement vector non-zero?
        if (KineticVelocity != Vector2.Zero)
        {
            // Yes, so add the vector to the position
            Position += KineticVelocity;
            // Ensure that the friction value is within range
            KineticFriction = MathHelper.Clamp(KineticFriction, 0, 1);
            // Apply 'friction' to the vector so that movement slows and stops
            KineticVelocity *= KineticFriction;
        }
    }

					  

With the help of this code, the objects can respond to being flicked, so now we need to establish how to provide them with an initial KineticVelocity in response to the user flicking them. The example projects both contain a function called ProcessFlick, which accepts a delta vector as a parameter and provides it to all the selected objects.

To calculate this flick delta using the gesture input system is very easy. We have already looked at the Flick gesture and seen how to translate its pixels-per-second Delta value into pixels-per-update. We can do this now and provide the resulting Vector2 value to the ProcessFlick function, as shown in Listing 15.

Example 15. Initiating object flicking using gesture inputs
while (TouchPanel.IsGestureAvailable)
        {
            GestureSample gesture = TouchPanel.ReadGesture();
            switch (gesture.GestureType)
            {
                case GestureType.Flick:
                    // The object has been flicked
                    ProcessFlick(gesture.Delta * (float)TargetElapsedTime.TotalSeconds);
                    break;
                 [... handle other gestures here...]
            }
        }

					  

Unfortunately, using raw input is a little more work. If we calculate the delta of just the final movement, we end up with a fairly unpredictable delta value because people tend to involuntarily alter their finger movement speed as they release contact with the screen. This is coupled with the fact that the Released state always reports the same position as the final Moved state, meaning that it alone doesn't provide us with any delta information at all.

To more accurately monitor the movement delta, we will build an array containing a small number of delta vectors (five is sufficient), and will add to the end of this array each time we process a Moved touch state. At the point of touch release, we can then calculate the average across the whole array and use it as our final movement delta.

This is implemented using three functions: ClearMovementQueue, AddDeltaToMovementQueue, and GetAverageMovementDelta. The first of these clears the array by setting all its elements to have coordinates of float.MinValue. We can look for this value when later processing the array and ignore any elements that have not been updated. ClearMovementQueue is called each time a new touch point is established with the screen.

AddDeltaToMovementQueue shifts all existing array elements down by one position and adds the provided delta to the end, as shown in Listing 16. This ensures that we always have the most recent delta values contained within the array, with older values being discarded. AddDeltaToMovementQueue is called each time we receive a touch point update with a state of Moved, with the delta vector calculated as described in the previous section.

Example 16. Adding new delta values to the movement queue
private void AddDeltaToMovementQueue(Vector2 delta)
    {
        // Move everything one place up the queue
        for (int i = 0; i < _movementQueue.Length - 1; i++)
        {
            _movementQueue[i] = _movementQueue[i + 1];
        }
        // Add the new delta value to the end
        _movementQueue[_movementQueue.Length - 1] = delta;
    }

Finally, the GetAverageMovementDelta calculates the average of the values stored within the array, as shown in Listing 17. Any items whose values are still set to float.MinValue are ignored. The returned vector is ready to be passed into the ProcessFlick function. Of course, the movement array is storing deltas in distance-per-update format, so we have no need to divide by the update interval as we did for gestures. GetAverageMovementDelta is called (along with ProcessFlick) when a touch point is detected with a state of Released.

Example 17. Calculating the average of the last five delta values
private Vector2 GetAverageMovementDelta()
    {
        Vector2 totalDelta = Vector2.Zero;
        int totalDeltaPoints = 0;

        for (int i = 0; i < _movementQueue.Length; i++)
        {
            // Is there something in the queue at this index?
            if (_movementQueue[i].X > float.MinValue)
            {
                // Add to the totalMovement
                totalDelta += _movementQueue[i];
                // Increment to the number of points added
                totalDeltaPoints += 1;
            }
        }
        // Divide the accumulated vector by the number of elements
        // to retrieve the average
        return (totalDelta / totalDeltaPoints);
    }

The main Update loop for the raw input example is shown in Listing 18. You will see here the situations that cause it to deselect objects, select objects, and reset the movement queue(when a new touch point is made), drag the objects and add their deltas to the movement queue (when an existing touch point is moved), and calculate the average and process the object flick (when a touch point is released).

Example 18. The update code for selecting, dragging, and flicking objects using raw touch data
// Get the raw touch input
        TouchCollection touches = TouchPanel.GetState();
        // Is there a touch?
        if (touches.Count > 0)
        {
            // What is the state of the first touch point?
            switch (touches[0].State)
            {
                case TouchLocationState.Pressed:
                    // New touch so select the objects at this position.
                    // First clear all existing selections
                    DeselectAllObjects();
                    // The select all touched sprites
                    SelectAllMatches(touches[0].Position);
                    // Clear the movement queue
                    ClearMovementQueue();
                    break;
                case TouchLocationState.Moved:
                    // Drag the objects. Make sure we have a previous position
                    TouchLocation previousPosition;
                    if (touches[0].TryGetPreviousLocation(out previousPosition))
                    {
                        // Calculate the movement delta
                        Vector2 delta = touches[0].Position - previousPosition.Position;
                        ProcessDrag(delta);
                        // Add the delta to the movement queue
                        AddDeltaToMovementQueue(delta);
                    }
                    break;
                case TouchLocationState.Released:
                    // Flick the objects by the average queue delta
                    ProcessFlick(GetAverageMovementDelta());
                    break;
            }
        }

					  

Try flicking the objects in each of the two DragAndFlick projects. The behavior of this operation is much more consistent between the two than it was for dragging. Also try experimenting with different friction values and see how this affects the motion of the objects when they are flicked.

5. Finger-Friendly Gaming

When designing the input mechanisms for your game, always be aware that people will use their fingers to control things. Unlike stylus input that was commonly used on earlier generations of mobile devices, fingers are inherently inaccurate when it comes to selecting from small areas on the screen.

With a little planning, you can help the user to have a comfortable experience despite this limitation; without any planning, you can turn your game into an exercise in frustration! If you have lots of objects that can be selected in a small area, give some thought to how you can help the user to select the object they actually desire rather than having them continually miss their target.

One option is to allow users to hold their finger on the screen and slide around to select an object rather than simply tapping an object. As they slide their finger, a representation of the selected object can be displayed nearby to highlight the current selection (which, of course, will be obscured by the finger). Once users have reached the correct place, they can release contact, happy that they have picked the object they desired.

Another possibility is to magnify the area of the screen surrounding the touch point, making all the objects appear larger. Users can then easily select the object they want, at which point the magnified area disappears.

Finger-friendly input options don't need to involve a lot of additional work, especially if they are planned and implemented early in a game's development, and it is definitely a good idea to avoid putting off your target audience with fiddly and unpredictable input mechanisms wherever possible.

Other -----------------
- Windows Phone 8 : Phone Hardware - Using Motion (part 2) - Emulating Motion
- Windows Phone 8 : Phone Hardware - Using Motion (part 1)
- Microsoft XNA Game Studio 3.0 : Adding Bread to Your Game (part 3) - Strange Bounce Behavior, Strange Edge Behavior
- Microsoft XNA Game Studio 3.0 : Adding Bread to Your Game (part 2) - Improving Programs Using Methods, Handling Collisions
- Microsoft XNA Game Studio 3.0 : Adding Bread to Your Game (part 1) - Using a Structure to Hold Sprite Information, Using the Gamepad Thumbsticks to Control Movement
- Business Apps for Android & Windows Phone 7 : Handyscan, Outdoor Navigation, Pageonce Money& Bills, Glympse, Cool Tools
- Windows Phone 7 Game Development : Orthographic Projection (part 2) - Isometric Projection & Pixel-Aligned Projection
- Windows Phone 7 Game Development : Orthographic Projection (part 1) - The Viewing Frustum & Defining the Orthographic Viewing Frustum in XNA
- Windows Phone 7 Game Development : Lighting (part 3) - Adding Lighting to Games
- Windows Phone 7 Game Development : Lighting (part 2) - How XNA Calculates Light Reflections
- Windows Phone 7 Game Development : Lighting (part 1) - Types of Illumination
- Windows Phone 7 : User Interface - Using Panorama and Pivot Controls
- Windows Phone 7 : User Interface - Localizing Your Application
- User Interface : Using the Windows Phone 7 Predefined Styles
- Handling Input on Windows Phone 7 : Touch Input (part 3) - Multi-Point Touch
- Handling Input on Windows Phone 7 : Touch Input (part 2) - Raw Touch with Mouse Events
- Handling Input on Windows Phone 7 : Touch Input (part 1) - Single-Point Touch
- Handling Input on Windows Phone 7 : The Keyboard
- User Interface : Customizing the Soft Input Panel Keyboard to Accept Only Numbers
- User Interface : Detecting Changes in the Theme Template
 
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
programming4us programming4us